﻿using ACMESharp.Authorizations;
using ACMESharp.Crypto;
using ACMESharp.Protocol;
using ACMESharp.Protocol.Resources;
using DnsClient;
using Service.Model;
using System.Text.RegularExpressions;

namespace Service
{
    public class CertService
    {
        private AcmeProtocolClient? acme;
        private OrderDetails? orderDetails;
        private LookupClient Dns = new LookupClient();
        private Authorization? Authorization;
        private string? Domain;
        public async Task<(Dns01ChallengeValidationDetails? Result, string Message)> Order(string txtEmail,string domain)
        {
            try
            {
                Domain = domain;
                // 设置你的Let's Encrypt API端点（生产或测试）
                var acmeDirectoryUri = "https://acme-v02.api.letsencrypt.org/directory"; // 生产环境
                //var acmeDirectoryUri = "https://acme-staging-v02.api.letsencrypt.org/directory"; // 测试环境
                var httpClient = new HttpClient();
                httpClient.BaseAddress = new Uri(acmeDirectoryUri);
                acme = new AcmeProtocolClient(httpClient, usePostAsGet: true);
                var dir = await acme.GetDirectoryAsync();
                acme.Directory = dir;
                await acme.GetNonceAsync();
                var email = $"mailto:{txtEmail}";
                var account = await acme.CreateAccountAsync(new[] { email }, true);
                acme.Account = account;
                orderDetails = await acme.CreateOrderAsync(new string[] { domain });
                Authorization = await acme.GetAuthorizationDetailsAsync(
                            orderDetails.Payload.Authorizations[0]);
                List<string> Message = new List<string>();
                var item = Authorization.Challenges[0];
                var chlngDetails = AuthorizationDecoder.ResolveChallengeForDns01(
                              Authorization, item, acme.Signer);
                return (chlngDetails, "请求发送成功");
            }
            catch (HttpRequestException ex)
            {
                return (null, "网络连接错误");
            }
            catch (Exception ex)
            {
                return (null, ex.Message);
            }
        }
        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="name"></param>
        /// <param name="targetValue"></param>
        /// <returns></returns>
        public async Task<(bool Result, string Message)> ValidateDnsTxtRecord(Dns01ChallengeValidationDetails dns)
        {
            var x = await Dns.QueryAsync(dns.DnsRecordName, QueryType.TXT);
            if (x.HasError)
            {
                return (false,x.ErrorMessage);
            }
            else
            {
                var targetValues = x.AllRecords.Where(s => s.DomainName.Value == $"{dns.DnsRecordName}.");
                var res = false;
                string pattern = @"(?<=TXT\s"")[^""]+(?="")";
                foreach (var item in targetValues)
                {
                    Match match = Regex.Match(item.ToString(), pattern);
                    if (match.Success)
                    {
                        if (dns.DnsRecordValue == match.Value)
                        {
                            res = true;
                            break;
                        }
                    }
                }
                return (res,"验证成功");
            }
        }
        /// <summary>
        /// 获取证书
        /// </summary>
        /// <returns></returns>
        public async Task<CertResult> GetCert()
        {
            return await Task.Run(async () =>
            {
                var result=new CertResult() { Successed=false,DomainName=Domain};
                try
                {
                    var challenge = await acme.GetChallengeDetailsAsync(Authorization.Challenges[0].Url);
                    if (challenge.Status == "pending")
                    {
                        await acme.AnswerChallengeAsync(Authorization.Challenges[0].Url);
                    }
                    else
                    {
                        result.Message = "域名所有权认证尚未成功,稍后再试";
                        return result;
                    }
                    int maxTry = 20;
                    int trySleep = 5 * 1000;
                    var valid = false;
                    for (var tryCount = 0; tryCount < maxTry; ++tryCount)
                    {
                        if (tryCount > 0)
                        {
                            Thread.Sleep(trySleep);
                            challenge = await acme.GetChallengeDetailsAsync(Authorization.Challenges[0].Url);
                            if (challenge.Status == "pending")
                            {
                                await acme.AnswerChallengeAsync(Authorization.Challenges[0].Url);
                            }
                        }
                        if (!valid)
                        {
                            if ("valid" == challenge.Status)
                            {
                                valid = true;
                                break;
                            }
                            else if ("pending" != challenge.Status)
                            {

                                result.Message = $"状态异常---{challenge.Status},重试";
                                return result;
                            }
                        }
                    }
                    maxTry = 20;
                    trySleep = 5 * 1000;
                    valid = false;
                    var rsaKeys = CryptoHelper.Rsa.GenerateKeys(4096);
                    var rsa = CryptoHelper.Rsa.GenerateAlgorithm(rsaKeys);
                    var derEncodedCsr = CryptoHelper.Rsa.GenerateCsr(orderDetails.Payload.Identifiers.Select(x => x.Value), rsa, "", "三丰", "三丰", "beijing", "beijing", "zh-cn");
                    var updatedOrder = await acme.FinalizeOrderAsync(orderDetails.Payload.Finalize, derEncodedCsr);
                    for (var tryCount = 0; tryCount < maxTry; ++tryCount)
                    {
                        if (tryCount > 0)
                        {
                            Thread.Sleep(trySleep);
                            updatedOrder = await acme.GetOrderDetailsAsync(orderDetails.OrderUrl);
                        }
                        if (!valid)
                        {
                            if ("valid" == updatedOrder.Payload.Status)
                            {
                                valid = true;
                            }
                            else if ("processing" == updatedOrder.Payload.Status)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (valid)
                    {
                        if (!string.IsNullOrEmpty(updatedOrder.Payload.Certificate))
                        {
                            var certBytes = await acme.GetByteArrayAsync(updatedOrder.Payload.Certificate);
                            result.PrivateRsa = rsa;
                            result.CertedCrt = certBytes;
                            result.Successed = true;
                            result.Message = "证书获取成功";
                            return result;
                        }
                    }
                    return new CertResult() { Successed = false, Message = "证书获取失败" };
                }
                catch (Exception ex)
                {
                    result.Successed = false;
                    result.Message = ex.Message;
                    return result;
                }
            });
        }
    }
}
